/**
 * Copyright (c) 2015-2020 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.support.http;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;

import com.yanlight.support.OkHttpFactory;
import com.yanlight.util.JsonUtil;
import com.yanlight.util.MapUtil;
import com.yanlight.util.XmlUtil;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.Request.Builder;

/**
 * 
 *
 * @author haolw
 * @time 2017/07/20
 */
public abstract class AbstractRequest<T> implements HttpConstants{
	private final Class<T> type;

	@SuppressWarnings("unchecked")
	public AbstractRequest() {
		this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public T execute() {
		RequestBuilder builder = RequestBuilder.newBuilder();
		execute(builder);
		Request request = buildRequest(builder);
		String result = execute(request);
		return execute(result, builder.getDataType());
	}

	private String execute(Request request) {
		OkHttpClient client = OkHttpFactory.getClient();
		Response response = null;
		String result = null;
		try {
			response = client.newCall(request).execute();
			result = response.body().string();
		} catch (IOException e) {
			throw new IllegalArgumentException("request network error");
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	private T execute(String result,String dataType) {
		if (String.class.isAssignableFrom(type)) {
			return (T) result;
		} else if (JSON.equals(dataType)) {
			return JsonUtil.parse(result, type);
		} else if (XML.equals(dataType)) {
			return XmlUtil.xmlToObject(result, type);
		}
		return null;
	}


	private Request buildRequest(RequestBuilder builder) {
		String url = builder.getUrl();
		String method = builder.getMethod();
		String contentType = builder.getContentType();
		String content = buildContent(builder);
		Builder requestBuilder = new Request.Builder();
		if (GET.equalsIgnoreCase(method)) {
			if (StringUtils.isNotBlank(content)) {
				url = url + "?" + content;
			}
			requestBuilder.url(url).get();
		} else if (POST.equalsIgnoreCase(method)) {
			RequestBody body = RequestBody.create(MediaType.parse(contentType), content);
			requestBuilder.url(url).post(body);
		}
		return requestBuilder.build();
	}
	
	private String buildContent(RequestBuilder builder) {
		Map<String, String> paramsMap = builder.getParamsMap();
		if (paramsMap == null || paramsMap.isEmpty()) {
			return null;
		}
		String content = "";
		String contentType = builder.getContentType();
		if (FORM.equals(contentType)) {
			content = MapUtil.toUrlParams(paramsMap);
		} else if (JSON.equals(contentType)) {
			content = JsonUtil.toJson(paramsMap);
		} else if (XML.equals(contentType)) {
			content = XmlUtil.mapToXml(paramsMap);
		}
		return content;
	}

	protected abstract void execute(RequestBuilder builder);

}
